package com.zhiqian.community.service;

import com.zhiqian.community.dao.CommentMapper;
import com.zhiqian.community.dao.DiscussPostMapper;
import com.zhiqian.community.entity.*;
import com.zhiqian.community.event.EventProducer;
import com.zhiqian.community.util.CommunityConstant;
import com.zhiqian.community.util.HostHolder;
import com.zhiqian.community.util.RedisKeyUtil;
import com.zhiqian.community.util.SensitiveFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.util.*;

@Service
public class CommentService implements CommunityConstant {
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private DiscussPostMapper discussPostMapper;
    @Autowired
    private SensitiveFilter sensitiveFilter;
    @Autowired
    private LikeService likeService;
    @Autowired
    private HostHolder hostHolder;
    @Autowired
    private EventProducer eventProducer;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询实体评论回复
     * @param entityType
     * @param entityId
     * @param page
     * @return
     */
    public List<Map<String,Object>> queryCommentsByEntity(Integer entityType, Integer entityId, Page page){
        User user = hostHolder.getUser();
        List<Map<String, Object>> commentVoList = new ArrayList<>();
        page.setLimit(10);
        List<Comment> comments = commentMapper.selectCommentsByEntity(entityType, entityId, page.getOffset(), page.getLimit());
        comments.stream().forEach(comment -> {
            HashMap<String, Object> commentVo = new HashMap<>();
            commentVo.put("comment", comment);
            commentVo.put("user", userService.getUserById(comment.getUserId()));
            commentVo.put("likeCount",likeService.queryEntityLikeCount(ENTITY_TYPE_COMMENT,comment.getId()));
            commentVo.put("userStatus",user!=null?likeService.queryEntityLikeStatus(user.getId(),ENTITY_TYPE_COMMENT,comment.getId()):0);
            List<Comment> replyList = commentMapper.selectCommentsByEntity(ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);
            List<Map<String,Object>> replyVoList=new ArrayList<>();
            replyList.stream().forEach(reply -> {
                HashMap<String, Object> replyVo = new HashMap<>();
                replyVo.put("reply",reply);
                replyVo.put("likeCount",likeService.queryEntityLikeCount(ENTITY_TYPE_COMMENT,reply.getId()));
                replyVo.put("userStatus",user!=null?likeService.queryEntityLikeStatus(user.getId(),ENTITY_TYPE_COMMENT,reply.getId()):0);
                replyVo.put("replyUser",userService.getUserById(reply.getUserId()));
                User target=reply.getTargetId()==0?null:userService.getUserById(reply.getTargetId());
                replyVo.put("target",target);
                replyVoList.add(replyVo);
            });
            commentVo.put("replys",replyVoList);
            commentVo.put("replyCount",replyVoList.size());
            commentVoList.add(commentVo);
        });
        return commentVoList;
    }

    public int queryCommentCountByEntity(Integer entityType,Integer entityId){
        return commentMapper.selectCommentCountByEntity(entityType,entityId);
    }

    /**
     * 添加评论
     * @param comment
     */
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    public int addComment(Comment comment,Integer postId){
        if (comment==null){
            throw new IllegalArgumentException("参数不能为空");
        }
        if (comment.getEntityType()==ENTITY_TYPE_POST) {
            discussPostMapper.incrementCommentCount(comment.getEntityId());
        }
        comment.setContent(sensitiveFilter.filter(HtmlUtils.htmlEscape(comment.getContent())));
        comment.setCreateTime(new Date());
        int rows = commentMapper.insertComment(comment);
        Event commentEvent = createCommentEvent(comment,postId);
        eventProducer.fireEvent(commentEvent);
        if (comment.getEntityType()==ENTITY_TYPE_POST) {
            Event postEvent = createPostEvent(comment, postId);
            eventProducer.fireEvent(postEvent);
            redisTemplate.opsForSet().add(RedisKeyUtil.getVariationPostKey(),postId);
        }
        return rows;
    }

    private Event createPostEvent(Comment comment, Integer postId) {
        Event event = new Event();
        event.setTopic(TOPIC_PUBLISH);
        event.setSourceId(comment.getUserId());
        event.setEntityType(ENTITY_TYPE_POST);
        event.setEntityId(postId);
        return event;
    }

    /**
     * 查询用户评论帖子的数量
     * @param userId
     * @return
     */
    public int selectUserCommentCount(Integer userId){
        return commentMapper.selectCommentCountByUserId(userId);
    }

    public List<Map<String,Object>> selectUserComments(Integer userId,Page page){
        List<Map<String,Object>> result = new ArrayList<>();
        List<Comment> comments = commentMapper.selectUserComments(userId, page.getOffset(), page.getLimit());
        comments.stream().forEach(comment -> {
            DiscussPost post = discussPostMapper.selectDiscussPostById(comment.getEntityId());
            if (post != null) {
                Map<String, Object> map = new HashMap<>(2);
                map.put("comment", comment);
                map.put("post", post);
                result.add(map);
            }
        });
        return result;
    }

    public Comment selectCommentById(Integer commentId){
        return commentMapper.selectCommentById(commentId);
    }

    private Event createCommentEvent(Comment comment,Integer postId){
        Event event = new Event();
        event.setTopic(TOPIC_COMMENT);
        event.setSourceId(comment.getUserId());
        event.setEntityId(comment.getEntityId());
        event.setEntityType(comment.getEntityType());
        event.setData("postId",postId);
        event.setData("sourceCommentId",comment.getId());
        if (comment.getEntityType()==ENTITY_TYPE_COMMENT){
            if (!comment.getTargetId().equals(0)) {
                event.setTargetId(comment.getTargetId());
            }else {
                Comment commentById = selectCommentById(comment.getEntityId());
                event.setTargetId(commentById.getUserId());
            }
        }else {
            DiscussPost post = discussPostMapper.selectDiscussPostById(postId);
            event.setTargetId(post.getUserId());
        }
        return event;
    }
}
